<template>
  <div class="upload-container">
    <div v-if="file" class="fileName" type="info" v-text="file === null ? '' : file.name"></div>
    <el-upload
        class="upload-demo"
        ref="upload"
        :action="url"
        :headers="headers"
        :show-file-list="false"
        :before-upload="beforeUpload"
        :on-change="handleChange"
        :on-progress="handleProgress"
        :on-success="handleSuccess"
        :on-error="handleError"
        :multiple="false"
        :auto-upload="false">
      <el-button slot="trigger" size="mini" type="primary">选取文件</el-button>
      <el-button style="margin-left: 10px;" :loading="uploading" size="mini" type="success" @click="submitUpload">上传到服务器</el-button>
      <el-progress v-if="progressBar.isShow" :percentage="progressBar.percentage"></el-progress>
    </el-upload>
    <div v-bind:style="{color: msg.color}" class="msg" v-text="msg.text"></div>
  </div>
</template>
<script>
import {AUTH_TOKEN,BaseURL} from "@/plugins/net";
import axios from "axios";

export default {
  name: 'BigFileUploader',
  props: {
    url: {
      type: String,
      default: BaseURL + "/file/upload"
    }
  },
  data() {
    return {
      file: null,
      data: null,
      headers: {
        Authorization: 'Bearer' + AUTH_TOKEN
      },
      progressBar: {
        isShow: false,
        percentage: 0
      },
      msg: {
        color: '',
        text: ''
      },
      uploading: false,
    }
  },
  methods: {
    handleChange(file,fileList) {
      this.file = file
      this.progressBar.percentage = 0
      this.msg.text = ''
    },
    beforeUpload(file) {

    },
    submitUpload() {
      this.uploading = true
      this.progressBar.isShow = true
      // 判断文件是否需要分片，大于5M就开启分片上传
      let isChunk = false;
      if (this.file.size >= 5 * 1024 * 1024) {
        isChunk = true
      }
      if (!isChunk) {
        // 不分片
        this.$refs.upload.submit();
      } else {
        // 分片
        // 每个分片大小规定为5M
        const chunkSize = 5 * 1024 * 1024
        // 总分片数
        const chunks = Math.ceil(this.file.size / chunkSize)
        // 任务组
        let tasks = []
        // 已经上传完成的片数，用于更新进度条
        let uploaded = 0;
        let config = {
          headers: {
            'Content-Type': 'multipart/form-data',
            'Authorization': 'Bearer ' + AUTH_TOKEN
          }
        }
        // 文件切割
        for(let i = 0; i < chunks; i++) {
          const start = i * chunkSize
          const end = Math.min(start + chunkSize,this.file.size)
          this.data = new FormData();
          this.data.append('is_chunk',true) // 是否分块
          this.data.append('chunk_index',i) // 块编号
          this.data.append('file_uid', this.file.uid) // 文件ID
          this.data.append('file_name',this.file.name) // 文件名
          this.data.append('type','0') // 分片上传请求
          this.data.append('file',this.file.raw.slice(start,end))
          tasks.push(new Promise((resolve,reject) => {
              axios.post(this.url,this.data,config).then(success => {
                    uploaded++
                    this.progressBar.percentage = Math.floor((uploaded / chunks) * 100)
                    resolve(success)
                  },
                  error => {
                    reject(error)
                  })
          }))
        }

        Promise.all(tasks).then((results) => {
          this.msg.text = '文件合并中...'
          this.data = new FormData()
          this.data.append('is_chunk',true) // 是否分块
          this.data.append('chunk_count',chunks) // 总块数
          this.data.append('file_uid', this.file.uid) // 文件ID
          this.data.append('file_name',this.file.name) // 文件名
          this.data.append('type','1') // 合并请求
          // 发起合并文件请求
          axios.post(this.url,this.data,config).then(res => {
            this.msg.text = '文件上传成功'
            this.uploading = false
            this.progressBar.percentage = 0
            this.progressBar.isShow = false
          })
        },error => {
          this.msg.text = '文件上传失败'
          this.uploading = false
          this.progressBar.percentage = 0
          this.progressBar.isShow = false
        })
      }
    },
    handleProgress(event, file) {
      // 显示上传进度
      this.progressBar.percentage = Math.floor((event.loaded / event.total) * 100);
    },
    handleSuccess(response,file,fileList) {
      this.msg.text = '上传成功'
      this.msg.color = 'gray'
      this.progressBar.isShow = false
      this.progressBar.percentage = 0
      this.uploading = false
    },
    handleError(err,file,fileList) {
      this.msg.text = '上传失败'
      this.msg.color = 'red'
      this.progressBar.isShow = false
      this.progressBar.percentage = 0
      this.uploading = false
    }
  },
}
</script>


<style scoped>

.upload-container {
  display: flex;
}

.upload-container > .fileName {
  background-color: rgba(128, 128, 128, 0.42);
  color: gray;
  margin-right: 4px;
  border-radius: 3px;
  font-size: 12px;
  padding: 0 6px;
  height: 27px;
  line-height: 27px;
}

.upload-container > .msg {
  margin-left: 4px;
  font-size: 12px;
  height: 27px;
  line-height: 27px;
}
</style>